package com.gy.nio;

import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * 使用nio完成网络通讯需要三个对象
 * 1。通道Channel
 * java.nio.channels.Channel借口
 * SocketChannel
 * ServerScoketChannel
 * DatagramChannel
 * 管道相关
 * Pipe.SinkChannel
 * Pipe.SourceChannel
 * <p>
 * 2.缓冲buffer:使用selectableChannel的所录复用器，要用用于监控selectableChannel的IO状况
 */
public class BlockingNIOTest {


    /**
     * 阻塞式的网络通讯：通过客户端socket想服务端scoket发送数据，服务端接受数据
     */
    @Test
    public void clinet() throws IOException {
        //或取通道
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 12121));

        //创建文件通道
        FileChannel inChannel = FileChannel.open(Paths.get("./mr/input.txt"), StandardOpenOption.READ);

        //分配指定大小的缓冲区
        ByteBuffer buf = ByteBuffer.allocateDirect(1024);

        //发送数据
        while (inChannel.read(buf) != -1) {
            buf.flip();
            socketChannel.write(buf);
            buf.clear();
        }

        //主动告诉服务端 数据已经发送完毕
        socketChannel.shutdownOutput();

        //接受响应
        while (socketChannel.read(buf) != -1) {
            buf.flip();
            System.out.println("接受成功 ");
            buf.clear();
        }

        inChannel.close();
        socketChannel.close();
    }


    @Test
    public void server() throws IOException {
        //或取通道
        ServerSocketChannel ssChannel = ServerSocketChannel.open();

        //创建输出通道，读取的内容写入文件
        FileChannel outChannel = FileChannel.open(Paths.get("./mr/input.txt.copy3"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);

        //绑定端口
        ssChannel.bind(new InetSocketAddress("127.0.0.1", 12121));

        //等待客户端连接，当连接成功，就会得到一个连接的通道
        SocketChannel channel = ssChannel.accept();

        //创建缓冲区
        ByteBuffer buf = ByteBuffer.allocateDirect(1024);

        //接受客户端的数据，处理
        while (channel.read(buf) != -1) {
            buf.flip();
            outChannel.write(buf);
            buf.clear();
        }

        //发送反馈给客户端
        buf.put("服务端接受数据成功".getBytes());
        buf.flip();
        channel.write(buf);


        buf.clear();
        ssChannel.close();
        outChannel.close();
    }

}
